package com.example.service;

import com.example.entity.NationLine;
import com.example.mapper.NationLineRepository;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

@Service
public class PredictionService {

    @Autowired
    private NationLineRepository nationLineRepository;
    // 预测分数的主要方法
    public double predictScore(String nationClass) {



        List<NationLine> lines = nationLineRepository.findByNationClass(nationClass);
        if (lines.size() < 2) {
            throw new IllegalArgumentException("Not enough data points to predict score.");
        }

        // 初始线性回归
        double[] coefficients = performRegression(lines);
        double a = coefficients[0];
        double b = coefficients[1];

        // 计算残差
        List<Double> residuals = calculateResiduals(lines, a, b);

        // 过滤异常值
        List<NationLine> filteredLines = filterOutliers(lines, residuals);

        if (filteredLines.isEmpty()) {
            throw new IllegalArgumentException("No data left after filtering outliers.");
        }

        // 执行最终的线性回归并返回预测值
        return performFinalRegression(filteredLines, a, b);
    }

    // 计算残差的方法
    private List<Double> calculateResiduals(List<NationLine> lines, double a, double b) {
        List<Double> residuals = new ArrayList<>();
        for (NationLine line : lines) {
            double predicted = a * line.getYear() + b;
            double residual = line.getLine() - predicted;
            residuals.add(residual);
        }
        return residuals;
    }

    // 过滤异常值的方法
    private List<NationLine> filterOutliers(List<NationLine> lines, List<Double> residuals) {
        double meanResidual = residuals.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        double stdDevResidual = Math.sqrt(residuals.stream().mapToDouble(d -> Math.pow(d - meanResidual, 2)).average().orElse(0.0));

        List<NationLine> filteredLines = new ArrayList<>();
        for (int i = 0; i < lines.size(); i++) {
            if (Math.abs(residuals.get(i)) <= 2 * stdDevResidual) {
                filteredLines.add(lines.get(i));
            }
        }
        return filteredLines;
    }

    // 执行初始线性回归的方法
    private double[] performRegression(List<NationLine> lines) {
        double sumX = 0.0, sumY = 0.0, sumX2 = 0.0, sumXY = 0.0;
        int n = lines.size();

        for (NationLine line : lines) {
            double x = line.getYear();
            double y = line.getLine();

            sumX += x;
            sumY += y;
            sumX2 += x * x;
            sumXY += x * y;
        }

        double xMean = sumX / n;
        double yMean = sumY / n;
        double denominator = sumX2 - n * xMean * xMean;

        // 检查除数是否为零，避免除以零的情况
        if (denominator == 0) {
            throw new ArithmeticException("Division by zero in calculation.");
        }

        double a = (sumXY - n * xMean * yMean) / denominator; // 斜率
        double b = yMean - a * xMean; // 截距

        // 返回斜率和截距的数组
        return new double[]{a, b};
    }

    // 执行最终的线性回归的方法
    private double performFinalRegression(List<NationLine> lines, double a, double b) {
        // 过滤异常值
        List<NationLine> filteredLines = filterOutliers(lines, calculateResiduals(lines, a, b));

        // 重新执行线性回归
        double[] newCoefficients = performRegression(filteredLines);
        double newA = newCoefficients[0];
        double newB = newCoefficients[1];

        // 返回重新计算的预测值
        return newA * 2025 + newB;
    }

    //        List<NationLine> lines = nationLineRepository.findByNationClass(nationClass);
//        SimpleRegression regression = new SimpleRegression();
//
//        for (NationLine line : lines) {
//            regression.addData(line.getYear(), line.getLine());
//        }
//
//        // 预测2025年的分数线
//        return regression.predict(2025);
//    }

//        List<NationLine> lines = nationLineRepository.findByNationClass(nationClass);
//
//        double sumX = 0.0, sumY = 0.0, sumX2 = 0.0, sumXY = 0.0;
//        int n = lines.size();
//
//        for (NationLine line : lines) {
//            double x = line.getYear();
//            double y = line.getLine();
//
//            sumX += x;
//            sumY += y;
//            sumX2 += x * x;
//            sumXY += x * y;
//        }
//
//        double xMean = sumX / n;
//        double yMean = sumY / n;
//
//        // 计算斜率a
//        double a = (sumXY - n * xMean * yMean) / (sumX2 - n * xMean * xMean);
//
//        // 计算截距b
//        double b = yMean - a * xMean;
//
//        // 使用模型预测2025年的分数线
//        return a * 2025 + b;
//    }

//        List<NationLine> lines = nationLineRepository.findByNationClass(nationClass);
//        List<Double> residuals = calculateResiduals(lines);
//
//        // 假设我们使用标准差来识别异常值
//        double meanResidual = residuals.stream().mapToDouble(d -> d).average().orElse(0.0);
//        double stdDevResidual = Math.sqrt(residuals.stream().mapToDouble(d -> Math.pow(d - meanResidual, 2)).average().orElse(0.0));
//
//        // 过滤掉差距过大的数据点
//        List<NationLine> filteredLines = lines.stream()
//                .filter(line -> Math.abs(line.getLine() - (line.getYear() * meanResidual + stdDevResidual)) < 2 * stdDevResidual)
//                .collect(Collectors.toList());
//
//        return performRegression(filteredLines);
//    }
//
//    private List<Double> calculateResiduals(List<NationLine> lines) {
//        double[] ab = calculateInitialRegression(lines);
//        double a = ab[0];
//        double b = ab[1];
//
//        return lines.stream()
//                .map(line -> line.getLine() - (a * line.getYear() + b))
//                .collect(Collectors.toList());
//    }
//
//    private double[] calculateInitialRegression(List<NationLine> lines) {
//        double sumX = 0.0, sumY = 0.0, sumX2 = 0.0, sumXY = 0.0;
//        int n = lines.size();
//        System.out.println("n: " + n );
//
//        for (NationLine line : lines) {
//            double x = line.getYear();
//            double y = line.getLine();
//
//            sumX += x;
//            sumY += y;
//            sumX2 += x * x;
//            sumXY += x * y;
//        }
//
//        double xMean = sumX / n;
//        double yMean = sumY / n;
//
////        double a = (sumXY - n * xMean * yMean) / (sumX2 - n * xMean * xMean);
//        double denominator = sumX2 - n * xMean * xMean;
//        if (denominator == 0) {
//            // 分母为零，无法计算斜率
//            return new double[]{Double.NaN}; // 或返回一个错误标志、抛出异常等
//        }
//        double a = (sumXY - n * xMean * yMean) / denominator;
//        double b = yMean - a * xMean;
//
//        System.out.println("xMean: " + xMean + ", yMean: " + yMean);
//        System.out.println("Denominator: " + denominator);
//        System.out.println("a: " + a + ", b: " + b);
//
//        return new double[]{a, b};
//
//    }
//
//    private double performRegression(List<NationLine> lines) {
//        double sumX = 0.0, sumY = 0.0, sumX2 = 0.0, sumXY = 0.0;
//        int n = lines.size();
//        System.out.println("n: " + n );
//
//        for (NationLine line : lines) {
//            double x = line.getYear();
//            double y = line.getLine();
//
//            sumX += x;
//            sumY += y;
//            sumX2 += x * x;
//            sumXY += x * y;
//        }
//
//        double xMean = sumX / n;
//        double yMean = sumY / n;
//
//        double a = (sumXY - n * xMean * yMean) / (sumX2 - n * xMean * xMean);
//        double b = yMean - a * xMean;
//
//        System.out.println("xMean1: " + xMean + ", yMean1: " + yMean);
//        System.out.println("a: " + a + ", b: " + b);
//
//        // 使用模型预测2025年的分数线
//        return a * 2025 + b;
//    }


 /*       // 获取数据库中指定专业的分数线数据
        List<NationLine> lines = nationLineRepository.findByNationClass(nationClass);
        // 检查数据点是否足够进行预测，至少需要两个数据点
        if (lines.size() < 2) {
            throw new IllegalArgumentException("Not enough data points to predict score.");
        }

        // 使用四分位数方法过滤异常值
        List<NationLine> filteredLines = filterOutliers(lines);
// 检查是否有足够的数据点用于回归分析
        if (filteredLines.isEmpty()) {
            throw new IllegalArgumentException("No data left after filtering outliers.");
        }

        return performRegression(filteredLines);
    }
    // 过滤异常值的方法
    private List<NationLine> filterOutliers(List<NationLine> lines) {
        // 提取分数数据并转换为Double类型
        List<Double> scores = lines.stream()
                .map(line -> (double) line.getLine()) // 将Integer转换为Double
                .sorted()
                .collect(Collectors.toList());

        int n = scores.size();
        double q1 = scores.get(n / 4);
        double q3 = scores.get(n * 3 / 4);
        double iqr = q3 - q1;

        double lowerBound = q1 - 1.5 * iqr;
        double upperBound = q3 + 1.5 * iqr;
// 过滤异常值，保留符合条件的数据点
        return lines.stream().filter(line -> {
            double score = (double) line.getLine(); // 将Integer转换为Double
            return score >= lowerBound && score <= upperBound;
        }).collect(Collectors.toList());
    }

    private double performRegression(List<NationLine> lines) {
        double sumX = 0.0, sumY = 0.0, sumX2 = 0.0, sumXY = 0.0;
        int n = lines.size();

        for (NationLine line : lines) {
            double x = line.getYear();
            double y = line.getLine();

            sumX += x;
            sumY += y;
            sumX2 += x * x;
            sumXY += x * y;
        }

        double xMean = sumX / n;
        double yMean = sumY / n;
        double denominator = sumX2 - n * xMean * xMean;
        if (denominator == 0) {
            throw new ArithmeticException("Division by zero in calculation.");
        }

        double a = (sumXY - n * xMean * yMean) / denominator;
        double b = yMean - a * xMean;

        // 使用模型预测2025年的分数线
        return a * 2025 + b;
    }  */

}
